package com.sunyzc.ebaotech.ybt.simulator;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sunyzc.ebaotech.ybt.simulator.util.IOUtil;
import com.sunyzc.ebaotech.ybt.simulator.util.YBTUtil;

public class SocketClient {
	private static final Logger log = LoggerFactory.getLogger(SocketClient.class);

	public static void main(String[] args) {
		boolean needCheckBill = true;
		String host = IProcessor.SERVER_HOST_YBT_LOCALHOST;
		String currentDate = null;
		int totalCount = 1;

		requesAlltYBTFront(host, currentDate, totalCount, needCheckBill);
	}

	public static void requesAlltYBTFront(String host, String currentDate, int totalCount, boolean needCheckBill) {
		// requestYBTFront("ABC", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("BOC", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("CCBNEW", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("BasicCCBNEW", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("ICBC", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("DGRCB", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("GZRCB", host, currentDate, totalCount, needCheckBill);
		// requestYBTFront("SDRCB", host, currentDate, totalCount, needCheckBill);
		requestYBTFront("POST", host, currentDate, totalCount, needCheckBill);
	}

	public static void requestYBTFront(String clientCode, String host, String currentDate) {
		if (clientCode != null && !clientCode.trim().equals("")) {
			try {
				IProcessor processor = (IProcessor) Class.forName(SocketClient.class.getPackage().getName() + "." + (clientCode.contains("CCBNEW") ? "ccbnew" : clientCode.toLowerCase()) + "." + clientCode + "Processor").newInstance();
				processor.setServerHost(host);
				processor.setCurrentDate(currentDate);
				requestYBTFront(processor, "1021", null);
				requestYBTFront(processor, "1022", null);
				requestYBTFront(processor, "8001", null);
			} catch (Throwable e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	public static void requestYBTFront(String clientCode, String host, String currentDate, int totalCount, boolean needCheckBill) {
		if (clientCode != null && !clientCode.trim().equals("")) {
			List<IProcessor> processorList = new ArrayList<IProcessor>();
			try {
				for (int index = 1; index <= totalCount; index++) {
					IProcessor processor = (IProcessor) Class.forName(SocketClient.class.getPackage().getName() + "." + (clientCode.contains("CCBNEW") ? "ccbnew" : clientCode.toLowerCase()) + "." + clientCode + "Processor").newInstance();
					log.info(processor.getClass().getSimpleName() + " 第 " + index + "/" + totalCount + " 次开始");
					processor.setServerHost(host);
					processor.setCurrentDate(currentDate);
					processorList.add(processor);
					if (clientCode.equals("ABC")) {
						requestYBTFront(processor, "1002", null);
						requestYBTFront(processor, "1004", null);
					} else if (clientCode.equals("BOC")) {
						requestYBTFront(processor, "1001", null);
						requestYBTFront(processor, "1002", null);
					} else if (clientCode.contains("CCBNEW")) {
						requestYBTFront(processor, "P53819113", null);
						requestYBTFront(processor, "P53819152", null);
					} else if (clientCode.equals("ICBC"))
						requestYBTFront(processor, "1013", null);
					else if (clientCode.equals("DGRCB") || clientCode.equals("GZRCB") || clientCode.equals("POST") || clientCode.equals("SDRCB")) {
						requestYBTFront(processor, "1021", null);
						requestYBTFront(processor, "1022", null);
					}
					log.info(processor.getClass().getSimpleName() + " 第 " + index + "/" + totalCount + " 次结束");
				}
			} catch (Throwable e) {
				log.error(e.getMessage(), e);
			}
			if (needCheckBill)
				try {
					if (clientCode.equals("ABC") || clientCode.equals("BOC"))
						requestYBTFront(processorList.get(0), "801", YBTUtil.generateCheckBillXmlTemplateStr(processorList, "801"));
					else if (clientCode.contains("CCBNEW"))
						requestYBTFront(processorList.get(0), "P53817103", YBTUtil.generateCheckBillXmlTemplateStr(processorList, "P53817103"));
					else if (clientCode.equals("ICBC") || clientCode.equals("DGRCB") || clientCode.equals("GZRCB") || clientCode.equals("POST") || clientCode.equals("SDRCB"))
						requestYBTFront(processorList.get(0), "8001", YBTUtil.generateCheckBillXmlTemplateStr(processorList, "8001"));
				} catch (Throwable e) {
					log.error(e.getMessage(), e);
				}
		}
	}

	public static String requestYBTFront(IProcessor processor, String transType, String requestBodyTemplateStr) throws Exception {
		Socket socket = null;
		BufferedOutputStream outputStream = null;
		BufferedInputStream inputStream = null;
		try {
			long startTime = System.currentTimeMillis();
			socket = new Socket(processor.getServerHost(), processor.getServerPort());
			log.info("Socket " + socket + " established ...");
			outputStream = new BufferedOutputStream(socket.getOutputStream());
			inputStream = new BufferedInputStream(socket.getInputStream());

			byte[] requestBodyContentBytes = processor.generateRequestBodyBytes(transType, requestBodyTemplateStr);
			byte[] requestHeadContentBytes = processor.generateHeadBytes(transType, requestBodyContentBytes);
			log.info("交易[" + transType + "]请求报文头: " + processor.convertContentBytesToStr(requestHeadContentBytes));
			log.debug("交易[" + transType + "]请求处理后的报文体: " + processor.convertContentBytesToStr(requestBodyContentBytes));

			outputStream.write(requestHeadContentBytes);
			outputStream.write(requestBodyContentBytes);
			outputStream.flush();

			String responseHeadContentStr = processor.readHeadConetentStr(transType, inputStream);
			String responseBodyContentStr = processor.readBodyConetentStr(transType, inputStream, responseHeadContentStr);
			log.info("交易[" + transType + "]响应报文头: " + responseHeadContentStr);
			log.info("交易[" + transType + "]响应报文体: " + responseBodyContentStr);
			log.info("交易[" + transType + "]用时 " + (System.currentTimeMillis() - startTime) + " 毫秒");

			return responseBodyContentStr;
		} finally {
			IOUtil.closeQuietly(outputStream);
			IOUtil.closeQuietly(inputStream);
			IOUtil.closeQuietly(socket);
			log.info("Socket " + socket + " closed.");
		}
	}
}
